//=============================================================================
//
//   Copyright (C) 2020 All rights reserved.
//
//   Filename:		linear_tfunc.rs
//
//   Author: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Date: 2020-10-08 02:25
//
//   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
//
//   Last modified:	2020-11-06 18:27
//
//   Description:
//
//=============================================================================
use crate::arith::time_func::time_func_interface::TimeFuncInterface;
use crate::Real;
use log::error;

#[derive(Debug)]
struct LinearTFuncion {
    svalue: Real,
    evalue: Real,
    stime: Real,
    etime: Real,
}
impl LinearTFuncion {
    pub fn new(svalue: Real, evalue: Real, stime: Real, etime: Real) -> Self {
        Self {
            svalue,
            evalue,
            stime,
            etime,
        }
    }
}

impl Default for LinearTFuncion {
    fn default() -> Self {
        Self {
            svalue: 0 as Real,
            evalue: 0 as Real,
            stime: 0 as Real,
            etime: 0 as Real,
        }
    }
}

impl TimeFuncInterface for LinearTFuncion {
    /// return value of function at given time step
    #[inline]
    fn get_value_at(&self, ctime: Real) -> Real {
        if (self.etime - self.stime).abs() < 1e-5 {
            error!(
                "linear time function has same start time {} and end time {}",
                self.stime, self.etime
            )
        };
        self.svalue + (self.evalue - self.svalue) * (ctime - self.stime) / (self.etime - self.stime)
    }
}

#[test]
fn simple_test() {
    use approx::assert_relative_eq;
    let tfunc = LinearTFuncion::new(0 as Real, 10 as Real, 0 as Real, 10 as Real);
    assert_relative_eq!(tfunc.get_value_at(3 as Real), 3 as Real, epsilon = 1e-3);
    assert_relative_eq!(tfunc.get_value_at(3 as Real), 3 as Real, epsilon = 1e-3);
    assert_relative_eq!(
        tfunc.get_increment_between(2 as Real, 5 as Real),
        3 as Real,
        epsilon = 1e-3
    );
    assert_relative_eq!(tfunc.get_slope_at(2 as Real), 1 as Real, epsilon = 1.1e-3);
}
